/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jili.ubert.server.tradecore;

import com.alibaba.fastjson.JSON;
import com.jili.ubert.dao.db.TradeReportDetail;
import com.jili.ubert.code.client2server.BasketOrders;
import com.jili.ubert.dao.db.NewOrder;
import com.jili.ubert.code.server2client.MsgResult;
import com.jili.ubert.dao.db.AccountBail;
import com.jili.ubert.dao.db.AccountFare;
import com.jili.ubert.dao.db.AccountInfo;
import com.jili.ubert.dao.db.PosDetail;
import com.jili.ubert.dao.db.ObjInfo;
import com.jili.ubert.code.ReturnIDEntity;
import com.jili.ubert.code.server2client.MsgResultList;
import com.jili.ubert.code.server2client.Price;
import com.jili.ubert.dao.db.AlterOrder;
import com.jili.ubert.dao.db.FundState;
import com.jili.ubert.dao.db.FundTransfer;
import com.jili.ubert.dao.db.OrderExecuteProgress;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.StampedLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author ChengJiLi
 */
public abstract class Position implements FundPos {

    private static final Log log = LogFactory.getLog(Position.class);

    public static Log getLog() {
        return log;
    }
    protected String accountCode;
    protected Double fundTotal;
    protected Double fundAvl;
    protected Double fundFroze;
    protected Double assetTotal;
    protected Double assetNet;
    protected Double assetCredit;
    protected Double posTotalValue;
    protected Double posNetValue;
    protected Double posCreditValue;
    protected String currency;
    protected Float rate;
    protected Double equalFundAvl;
    protected Double befAssetTotal;
    protected Double befFundAvl;
    
    protected final ConcurrentHashMap<Integer, FrozeOrder> frozeOrders = new ConcurrentHashMap<>();
    protected HashMap<String, Fare> fareTable = new HashMap<>();//key：证券：市场，品种,买卖；期货：市场，品种，元资产，合约，买卖，开平
    protected HashMap<String, Bail> bailTable = new HashMap<>();//期货：市场，品种，元资产，合约，买卖，开平
    //key:obj,mk,bs,posID
    protected final ConcurrentHashMap<String, PosRecord> posTable = new ConcurrentHashMap<>();
    private final StampedLock fundsl = new StampedLock();
    private final StampedLock possl = new StampedLock();
    private final StampedLock frozesl = new StampedLock();
    protected HashMap<String, Price> priceTable;
    protected final ConcurrentHashMap<Integer, NewOrder> newOrderTable = new ConcurrentHashMap<>();
    protected final ConcurrentHashMap<Integer, AlterOrder> alterOrderTable = new ConcurrentHashMap<>();
    protected final ConcurrentHashMap<Integer, OrderExecuteProgress> exeOrderTable = new ConcurrentHashMap<>();//key:OrderID
    
    public abstract void setData(Fare data);
    public abstract void setData(Bail data);
    public abstract void setData(PosRecord data);
    public abstract void setData(FundState data);
    

    //锁定义
    //资金调整锁
    //持仓调整锁
    //在途订单锁
    //盈亏锁
    /*
    成员数据，初始化重量级：资金结算表，持仓明细表；费率表，保证金表
    中间数据表：冻结在途订单表
     */
    //外部调用
    public abstract MsgResult CheckOrder(NewOrder order);

    public abstract MsgResultList CheckBasketOrder(BasketOrders orders);

    public abstract MsgResult CheckOrder(AlterOrder alterOrder);

    public MsgResult CheckOrderlmp(NewOrder order) {
        MsgResult rst;
        switch (order.getTradeOperate()) {
            case 1: {
                rst = CheckFund(order);
                break;
            }
            case 2: {
                rst = CheckPos(order);
                break;
            }
            case 3: {
                rst = CheckFund(order);
                break;
            }
            case 4: {
                rst = CheckFund(order);
                break;
            }
            case 5: {
                rst = CheckPos(order);
                break;
            }
            case 6: {
                rst = CheckPos(order);
                break;
            }
            case 7: {
                rst = CheckPos(order);
                break;
            }
            case 8: {
                rst = CheckPos(order);
                break;
            }
            case 9: {
                rst = CheckPos(order);
                break;
            }
            case 10: {
                rst = CheckPos(order);
                break;
            }
            case 11: {
                rst = CheckPos(order);
                break;
            }
            case 12: {
                rst = CheckPos(order);
                break;
            }
            case 13: {
                rst = CheckFund(order);
                break;
            }
            case 14: {
                rst = CheckPos(order);
                break;
            }
            case 15: {
                rst = CheckFund(order);
                break;
            }
            case 16: {
                rst = CheckPos(order);
                break;
            }
            case 17: {
                rst = CheckPos(order);
                break;
            }
            case 18: {
                rst = CheckPos(order);
                break;
            }
            case 19: {
                rst = CheckPos(order);
                break;
            }
            case 20: {
                rst = CheckPos(order);
                break;
            }
            case 21: {
                rst = CheckPos(order);
                break;
            }
            case 22: {
                rst = CheckPos(order);
                break;
            }
            case 23: {
                rst = CheckPos(order);
                break;
            }
            case 24: {
                rst = CheckPos(order);
                break;
            }
            case 25: {
                rst = CheckPos(order);
                break;
            }
            case 26: {
                rst = CheckPos(order);
                break;
            }
            case 27: {
                rst = CheckPos(order);
                break;
            }
            case 28: {
                rst = CheckPos(order);
                break;
            }
            case 29: {
                rst = CheckPos(order);
                break;
            }
            case 30: {
                rst = CheckPos(order);
                break;
            }
            case 31: {
                rst = CheckPos(order);
                break;
            }
            default: {
                rst = ReturnIDEntity.notDealTrade;
                break;
            }
        }
        return rst;
    }

    public void saveOrder(int oid, NewOrder order) {
        newOrderTable.put(oid, order);
        OrderExecuteProgress oep = new OrderExecuteProgress();
        updateOrderExecuteProgressByNewOrder(oep, order);
        exeOrderTable.put(oid, oep);
    }
    public void saveOrder(NewOrder order) {
        int oid = order.getOrderID();
        newOrderTable.put(oid, order);
        OrderExecuteProgress oep = new OrderExecuteProgress();
        updateOrderExecuteProgressByNewOrder(oep, order);
        oep.setOrderStatus("A");
        exeOrderTable.put(oid, oep);
    }
    public void deleteOrder(int oid) {
        if (newOrderTable.containsKey(oid)){
            newOrderTable.remove(oid);
        }
        if (exeOrderTable.containsKey(oid)){
            exeOrderTable.remove(oid);
        }
    }

    public void FundAdjust(double amont) {
        long stamp = getFundsl().writeLock();
        try {
            this.fundAvl = this.fundAvl + amont;
            this.fundTotal = this.fundAvl + amont;
        } finally {
            getFundsl().unlockWrite(stamp);
        }
    }

    public MsgResult TranseferFund(double amount) {
        MsgResult rst;
        double avlfund = this.getFundAvl();
        if (avlfund >= amount) {
            FundAdjust(amount);
            rst = ReturnIDEntity.Success;
        } else {
            rst = ReturnIDEntity.notEnoughFAL(avlfund);
        }
        return rst;
    }

    //内部调用,持仓调整
    protected void PosAdjust(String poskey, int qty) {
        //    long stamp = getFundsl().writeLock();
        PosRecord posrecord = posTable.get(poskey);
        posrecord.setAvlQty(posrecord.getAvlQty() + qty);
        posrecord.setQty(posrecord.getQty() + qty);
        posrecord.setFrozeQty(posrecord.getFrozeQty() - qty);
        /*    
        try {
            this.fundAvl = this.getFundAvl() + qty;
        } finally {
            getFundsl().unlockWrite(stamp);
        }
         */
    }

    //验资，订单检查用
    protected MsgResult CheckFund(NewOrder order) {
        MsgResult rst;
        //1.计算金额,证券不处理保证金；期货的直接在这个函数下处理保证金率；
        double exeamt = EstimateExeAmont(order);
        //2.计算费用，调用获取费率的方法
        double[] fares = CalcFare(order, exeamt);
        //3.计算所需资金，实现类可以改写这个函数
        double requireFund = RequireFund(exeamt, fares);
        rst = FrozeFund(order, requireFund, fares[0]);
        updateOrderExecuteProgress(order.getOrderID(),fares);
        rst.setAmount(fares);//成功不成功都放上资金及费用；
//        rst.setRemark("需要冻结金额：" + amt + "明细为：" + JSON.toJSONString(fares));
        return rst;
    }

    //验券，订单检查用
    protected MsgResult CheckPos(NewOrder order) {
        MsgResult rst;
        String bs = order.getBs().equals("B") ? "S" : "B";
        String poskey = order.getObj().concat("_").concat(order.getMarketCode()).concat("_").concat(bs).concat("_").concat(order.getPosID());
        if (posTable.containsKey(poskey)) {
            rst = FrozePos(poskey, order);
        } else {
            rst = ReturnIDEntity.notEnoughPos(0);
        }
        return rst;
    }

    //冻结持仓，验券用
    protected MsgResult FrozePos(String poskey, NewOrder order) {
        MsgResult rst;
        int aqty = posTable.get(poskey).getAvlQty();
        int qty = order.getOrderQty();
        if (aqty >= qty) {
            PosAdjust(poskey, -qty);
            FrozeOrder frozeorder = new FrozeOrder(order);
            frozeorder.setPosID(poskey);
            frozeorder.setFundFroze(false);
            this.frozeOrders.put(order.getOrderID(), frozeorder);
            saveOrder(order);
            rst = ReturnIDEntity.Success;
        } else {
            rst = ReturnIDEntity.notEnoughPos(aqty);
        }
        return rst;
    }

    //冻结资金，验资用
    protected MsgResult FrozeFund(NewOrder order, double amount, double fare) {
        MsgResult rst;
        double f = this.getFundAvl();
        if (amount <= f) {//检查可用
            FundAdjust(-amount);
            FrozeOrder frozeorder = new FrozeOrder(order);
            frozeorder.setFrozeFund(amount);
            frozeorder.setFare(fare);
            frozeorder.setFundFroze(true);
            this.frozeOrders.put(order.getOrderID(), frozeorder);
            saveOrder(order);
            rst = ReturnIDEntity.Success;
        } else {
            rst = ReturnIDEntity.notEnoughFAL(f);
        }
        return rst;
    }

    public NewOrder transferNewOrder(TradeReportDetail report) {
        NewOrder order = new NewOrder();
        order.setAccountCode(report.getAccountCode());
        order.setObj(order.getObj());
        order.setBs(report.getBs());
        order.setOpenClose(order.getOpenClose());
        order.setOrderID(report.getOrderID());
        order.setClassCode(report.getClassCode());//补充
        order.setOrderPrice(report.getPrice());
        order.setOrderQty(report.getWorkingQty());
        order.setHedgeFlag(report.getHedgeFlag());
    //    order.setDealerUserID(report.get);
        order.setSubmitTime(report.getSubmitTime());
        order.setMarketCode(report.getMarketCode());
        order.setTradeOperate(0);
        return order;
    }

    //解冻资金，内部回报用，外部订单管理用
    public void UnFrozeFund(int orderid) {
        double amount = frozeOrders.get(orderid).getFrozeFund();
        frozeOrders.remove(orderid);
        FundAdjust(amount);
    }

    //解冻资金，内部回报用，外部订单管理用
    public MsgResult UnFrozeOrder(int orderid) {
        MsgResult ret;
        if (frozeOrders.containsKey(orderid)) {
            if (frozeOrders.get(orderid).isFundFroze()) {
                UnFrozeFund(orderid);
            } else {
                UnFrozePos(orderid);
            }
            ret = ReturnIDEntity.Success;
        } else {
            ret = ReturnIDEntity.noFrozeOrder(orderid);
        }
        return ret;
    }

    public MsgResult UnFrozeOrder(int orderid, int qty) {
        MsgResult ret;
        if (frozeOrders.containsKey(orderid)) {
            if (frozeOrders.get(orderid).isFundFroze()) {
                UnFrozeFund(orderid, qty);
            } else {
                UnFrozePos(orderid, qty);
            }
            ret = ReturnIDEntity.Success;
        } else {
            ret = ReturnIDEntity.noFrozeOrder(orderid);
        }
        return ret;
    }

    public void UnFrozeFund(int orderid, int qty) {
        FrozeOrder frozeorder = frozeOrders.get(orderid);
        int frozeqty = frozeorder.getQty();
        if (qty >= frozeqty) {
            double amount = frozeorder.getFrozeFund();
            frozeOrders.remove(orderid);
            FundAdjust(amount);
        } else {
            double amount = qty * frozeorder.getPrice();
            int qty0 = frozeqty - qty;
            frozeorder.setQty(qty0);
            FundAdjust(amount);
        }
    }

    //解冻持仓，内部回报用，外部订单管理用
    public void UnFrozePos(int orderid) {
        FrozeOrder frozeorder = frozeOrders.get(orderid);
        int qty = frozeorder.getQty();
        String poskey = frozeorder.getPosID();
        frozeOrders.remove(orderid);
        if (posTable.containsKey(poskey)) {
            PosAdjust(poskey, qty);
        } else {
            posTable.put(poskey, new PosRecord(frozeorder));
            PosAdjust(poskey, qty);
        }
    }

    public void UnFrozePos(int orderid, int qty) {
        FrozeOrder frozeorder = frozeOrders.get(orderid);
        int frozeqty = frozeorder.getQty();
        String poskey = frozeorder.getPosID();
        if (qty >= frozeqty) {
            frozeOrders.remove(orderid);
        } else {
            frozeorder.setQty(frozeqty - qty);
        }
        if (posTable.containsKey(poskey)) {
            PosAdjust(poskey, qty);
        } else {
            posTable.put(poskey, new PosRecord(frozeorder));
            PosAdjust(poskey, qty);
        }
    }

    public int dealExeFrozeOrder(int orderid, int exeqty, double exeamount) {
        if (frozeOrders.get(orderid).isFundFroze()) {
            return UnFrozeFundToPos(orderid, exeqty, exeamount);
        } else {
            return UnFrozePosToFund(orderid, exeqty, exeamount);
        }
    }

    //解冻资金转持仓，内部回报用,调用前要生成持仓；否则不兼容
    protected int UnFrozeFundToPos(int orderid, int qty, double exeamount) {
        if (frozeOrders.containsKey(orderid)) {
            FrozeOrder order = frozeOrders.get(orderid);
            int ret = 0;
            int frozeqty = order.getQty();
            double frozefund = order.getFrozeFund();
            String poskey = order.getObj().concat("_").concat(order.getMarketCode()).concat("_").concat(order.getBs()).concat("_").concat(order.getPosID());
            if (qty >= frozeqty) {
                frozeOrders.remove(orderid);
                PosAdjust(poskey, frozeqty);
                return qty - frozeqty;
            } else {
                order.setQty(frozeqty - qty);
                order.setFrozeFund(frozefund-exeamount);
                PosAdjust(poskey, qty);
                return 0;
            }
        } else {//外部单
            return qty;
        }
    }

    //解冻持仓转资金，内部回报用
    protected int UnFrozePosToFund(int orderid, int qty, double amount) {
        int ret = 0;
        FrozeOrder order = frozeOrders.get(orderid);
        String poskey = order.getObj().concat("_").concat(order.getMarketCode()).concat("_").concat(order.getBs()).concat("_").concat(order.getPosID());
        int frozeqty = order.getQty();
        if (qty>=frozeqty){
            frozeOrders.remove(orderid);
            reCalcFare(this.exeOrderTable.get(orderid));
            if (qty>frozeqty){
            FundAdjust(frozeqty*amount/qty);}
            else{
                FundAdjust(amount);
            }
        }else{
            order.setQty(frozeqty - qty);
            FundAdjust(amount);
        }
        return ret;
    }

    //计算冻结金额，验资用
    protected double RequireFund(double exeamount, double[] fares) {
        double a = exeamount + fares[0];
        fares[5] = a;
        return a;
    }

    //预估成交金额
    protected double EstimateExeAmont(NewOrder order) {
        double amt;
        if (order.getPriceType().equals("1")) {
            amt = order.getOrderQty() * order.getOrderPrice();
        } else {
            double price;
            Price pc = getPriceTable().get(order.getObj() + "_" + order.getMarketCode());
            if (order.getBs().equals("B")) {
                if (pc.getUpperLimitPrice() != 0) {
                    price = pc.getUpperLimitPrice();
                } else {
                    price = pc.getLNC() * (1 + 0.1);
                }

            } else if (pc.getUpperLimitPrice() != 0) {
                price = pc.getUpperLimitPrice();
            } else {
                price = pc.getLNC() * (1 - 0.1);
            }
            amt = order.getOrderQty() * price;
            order.setOrderPrice((float) price);
        }
        return amt;
    }

    public double[] CalcFare(NewOrder order, double amt) {
        double[] rst = new double[6];
        /*
         0:总费用，1：佣金，2：税，3：过户费，4：交易所非，5:每手保证金,6:保证金率
         */
        Fare fare = getFare(order.getMarketCode(), order.getClassCode(), order.getBs());
        if (fare != null) {
            rst[1] = fare.getCommission0() * amt < fare.getMinCommission0() ? fare.getMinCommission0() : fare.getCommission0() * amt;
            rst[2] = fare.getTax0() * amt;
            rst[3] = fare.getDeliverFare0() * amt;
            rst[4] = fare.getCost0() * amt;
            rst[0] = rst[1] + rst[2] + rst[3] + rst[4];
        }
        return rst;
    }
    public double[] reCalcFare(OrderExecuteProgress order) {
        double[] rst = new double[6];
        double amt = order.getExeAmount();
        /*
         0:总费用，1：佣金，2：税，3：过户费，4：交易所非，5:每手保证金,6:保证金率
         */
        Fare fare = getFare(order.getMarketCode(), order.getClassCode(), order.getBs());
        if (fare != null) {
            rst[1] = fare.getCommission0() * amt < fare.getMinCommission0() ? fare.getMinCommission0() : fare.getCommission0() * amt;
            rst[2] = fare.getTax0() * amt;
            rst[3] = fare.getDeliverFare0() * amt;
            rst[4] = fare.getCost0() * amt;
            rst[0] = rst[1] + rst[2] + rst[3] + rst[4];
        }
        order.setTotalFare((float)rst[0]);
        order.setTax((float)rst[2]);
        order.setCommissionFare((float)rst[1]);
        order.setDeliverFare((float)rst[3]);
        order.setOtherCost((float)rst[4]);
        this.FundAdjust(rst[0]);
        return rst;
    }

    public Fare getFare(String mk, String cc, String bs) {
        Fare fare = null;
        if (fareTable.containsKey(mk + cc)) {
            fare = fareTable.get(mk + cc);
        }
        if (fareTable.containsKey(mk + cc + bs)) {
            fare = fareTable.get(mk + cc + bs);
        }
        return fare;
    }

    public Fare getFare(String mk, String code, String obj, String bs, String op) {
        Fare fare = null;
        if (fareTable.containsKey(mk + code)) {
            fare = fareTable.get(mk + code);
        }
        if (fareTable.containsKey(mk + code + obj)) {
            fare = fareTable.get(mk + code + obj);
        }
        if (fareTable.containsKey(mk + code + obj + bs)) {
            fare = fareTable.get(mk + code + obj + bs);
        }
        if (fareTable.containsKey(mk + code + obj + bs + op)) {
            fare = fareTable.get(mk + code + obj + bs + op);
        }
        return fare;
    }

    public Bail getBail(String mk, String code, String obj, String bs) {
        Bail bail = null;
        if (bailTable.containsKey(mk + code)) {
            bail = bailTable.get(mk + code);
        }
        if (bailTable.containsKey(mk + code + obj)) {
            bail = bailTable.get(mk + code + obj);
        }
        if (bailTable.containsKey(mk + code + obj + bs)) {
            bail = bailTable.get(mk + code + obj + bs);
        }
        return bail;
    }

    //---------------------------------------------------------------------------------------------
    //验券
    /*
     1.委托回报：MsgType:C1：下单回报，C2:撤单回报,C3:改价回报
     1)模拟成交：OR:订单委托回报，OS:订单成交回报；CR:撤单委托回报，CS:撤单成交回报；AR改单委托回报，AS：改单成交回报；OO：其他指令单回报
     2）内部成交：IS:内部成交回报，IC：内部撤单回报，IA: 内部改单回报；注意，内部成交不需要委托确认，直接处理结果
     3）内部移仓：PS：内部移仓成交回报
     4）状态修订：ST:状态修复回报
     2.多态处理，接收3种委托
     type:1.模拟成交，2.内部成交，3.内部移仓，4.状态修改；OrderType只在type为1的时候有效
     */
    public void updateOrderExecuteProgressByNewOrder(OrderExecuteProgress oep, NewOrder order) {
        oep.setAccountCode(order.getAccountCode());
        oep.setBasketID(order.getBasketID());
        oep.setBasketTatol(order.getBasketTatol());
        oep.setBs(order.getBs());
        oep.setClassCode(order.getClassCode());
        oep.setCloseType(order.getCloseType());
        oep.setCustomCode(order.getCustomCode());
        oep.setDateTime(order.getDateTime());
        oep.setDealerUserID(order.getDealerUserID());
        oep.setHedgeFlag(order.getHedgeFlag());
        oep.setInvestID("");
        oep.setIp4(order.getIp4());
        oep.setMac(order.getMac());
        oep.setMarketCode(order.getMarketCode());
        oep.setObj(order.getObj());
        oep.setOpenClose(order.getOpenClose());
        oep.setOrderID(order.getOrderID());
        oep.setOrderQty(order.getOrderQty());
        oep.setOrderStatus("A");
        oep.setOrderTypeEmit(order.getOrderTypeEmit());
        oep.setPosID(order.getPosID());
    }

    public void updateOrderExecuteProgress(int orderid, double[] fares) {
        if (this.exeOrderTable.containsKey(orderid)) {
            OrderExecuteProgress order = exeOrderTable.get(orderid);
            order.setTotalFare((float)fares[0]);
        order.setTax((float)fares[2]);
        order.setCommissionFare((float)fares[1]);
        order.setDeliverFare((float)fares[3]);
        order.setOtherCost((float)fares[4]);
        } 
    }

    public void updateOrderExecuteProgressConfirm(TradeReportDetail report) {
        int orderid = report.getOrderID();
            OrderExecuteProgress oep = exeOrderTable.get(orderid);
            oep.setWorkingQty(report.getWorkingQty());
            oep.setSubmitTime(report.getEntrustTime());
            oep.setOrderStatus("B");
    }

    public void updateOrderExecuteProgress(TradeReportDetail report) {
        int orderid = report.getOrderID();
        if (this.exeOrderTable.containsKey(orderid)) {
            OrderExecuteProgress oep = exeOrderTable.get(orderid);  
            int exeqty = report.getExeQty();
            if (exeqty!=0){
                oep.setExeQty(oep.getExeQty()+report.getExeQty());
                oep.setExePrice(report.getExePriceAvg());
                oep.setExeAmount(oep.getExeAmount()+report.getExeAmount());
                oep.setExeTime(report.getExeTime());
                oep.setCompleteQty(oep.getCompleteQty()+report.getExeQty());
                oep.setWorkingQty(oep.getWorkingQty()-report.getExeQty());
            }else{
                oep.setExeQty(report.getExeQtyTatol()-oep.getCompleteQty());
                oep.setCompleteQty(report.getExeQtyTatol());
                oep.setExePrice(report.getExePriceAvg());
                oep.setExeAmount(report.getExeAmount());
                oep.setExeTime(report.getExeTime());
                oep.setWorkingQty(oep.getOrderQty()-report.getExeQtyTatol());
            }
            if (oep.getWorkingQty()==0){
                oep.setOrderStatus("E");
            }else{
                oep.setOrderStatus("C");
            }
        }
    }

    public void OnReportOrderConfirm(TradeReportDetail report) {
        /*
        1.更新状态表
         */
        int orderid = report.getOrderID();
        if (!this.exeOrderTable.containsKey(orderid)) {
            NewOrder order = transferNewOrder(report);
            this.CheckOrderlmp(order);
        } else {
            updateOrderExecuteProgressConfirm(report);
        }

    }

    public void OnReportOrderExe(TradeReportDetail report) {
        //更新状态表；处理成交
        int orderid = report.getOrderID();
        int qty = report.getExeQty();
        double exeamount = report.getExeAmount();
        updateOrderExecuteProgress(report);
        dealExeFrozeOrder(orderid, qty, exeamount);
    }

    public void OnReportCancelOrder(TradeReportDetail report) {
        //更新状态表，处理撤单手数
        int orderid = report.getOrderID();
        OrderExecuteProgress oep = this.exeOrderTable.get(orderid);
        int unworkingqty = report.getUnWorkingQty();
        oep.setCancelQty(unworkingqty);
        oep.setOrderStatus("D");
        this.UnFrozeOrder(orderid, unworkingqty);
        reCalcFare(oep);
        
    }

    public void OnTradeReport(TradeReportDetail report) {
        String stat = report.getMsgType();
        if (report.getReportNo() == 1) {//正常成功的回报
            switch (stat) {
                case "OR": {//OR:订单委托回报
                    OnReportOrderConfirm(report);
                    break;
                }
                case "OS": {//OS:订单成交回报
                    OnReportOrderExe(report);
                    break;
                }
                case "IS": {//IS:内部成交回报
                    OnReportOrderExe(report);
                    break;
                }
                case "CS": {//CS:撤单成交回报
                    OnReportCancelOrder(report);
                    break;
                }
                case "IC": {//IC：内部撤单回报
                    OnReportCancelOrder(report);
                    break;
                }
                case "IA": {//IA: 内部改单回报

                    break;
                }
                case "AR": {//AR改单委托回报
                    break;
                }
                case "AS": {//AS：改单成交回报

                    break;
                }
                case "OO": {//OO：其他指令单回报
                    break;
                }
                case "PS": {//PS：内部移仓成交回报
                    break;
                }
                case "ST": {//ST:状态修复回报
                    break;
                }
            }
        } else//拒绝或失败的回报
        {
            if (stat.equals("OR")) {
                int orderid = report.getOrderID();
                this.UnFrozeOrder(orderid);
            }
        }
    }

    /*
    取值封装，主要是不可设置，处理读写锁的
     */
    public String getAccountCode() {
        return accountCode;
    }

    public Double getFundTotal() {
        long stamp = fundsl.tryOptimisticRead();
        double o = fundTotal;
        if (!fundsl.validate(stamp)) {
            stamp = fundsl.readLock();
            try {
                o = fundTotal;
            } finally {
                fundsl.unlockRead(stamp);
            }
        }
        return o;
    }

    public Double getFundAvl() {
        long stamp = fundsl.tryOptimisticRead();
        double o = fundAvl;
        if (!fundsl.validate(stamp)) {
            stamp = fundsl.readLock();
            try {
                o = fundAvl;
            } finally {
                fundsl.unlockRead(stamp);
            }
        }
        return o;
    }

    public Double getFundFroze() {
        return fundFroze;
    }

    public Double getAssetTotal() {
        return assetTotal;
    }

    public Double getAssetNet() {
        return assetNet;
    }

    public Double getAssetCredit() {
        return assetCredit;
    }

    public Double getPosTotalValue() {
        return posTotalValue;
    }

    public Double getPosNetValue() {
        return posNetValue;
    }

    public Double getPosCreditValue() {
        return posCreditValue;
    }

    public String getCurrency() {
        return currency;
    }

    public Float getRate() {
        return rate;
    }

    public Double getEqualFundAvl() {
        return equalFundAvl;
    }

    public Double getBefAssetTotal() {
        return befAssetTotal;
    }

    public Double getBefFundAvl() {
        return befFundAvl;
    }

    public ConcurrentHashMap<Integer, FrozeOrder> getFrozeOrders() {
        return frozeOrders;
    }

    public StampedLock getFundsl() {
        return fundsl;
    }

    public StampedLock getPossl() {
        return possl;
    }

    public StampedLock getFrozesl() {
        return frozesl;
    }

    public HashMap<String, Price> getPriceTable() {
        return priceTable;
    }
}
